package com.xpalive.utils.beans;

import com.xpalive.exception.BizException;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import lombok.Getter;
import lombok.Setter;
import net.sf.cglib.beans.BeanCopier;
import org.apache.commons.lang3.StringUtils;

public class XBeanUtils {

    /**
     * DateLimit dateLimit = new DateLimit(); dateLimit.setRule(CalendarRule.INCLUDE);
     * ZWBeanUtils.processBean(dateLimit) .defIfNull(DateLimit::getRule, CalendarRule.EXCLUDE);
     * System.out.println(dateLimit.getRule());
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> BeanDefVal<T> processBean(T t) {
        BeanDefVal<T> tBeanDefVal = new BeanDefVal<>(t);
        return tBeanDefVal;
    }

    //获取对象filed 包含父类
    public static Field getDeclaredField(Class<?> tClass, String fieldName)
        throws NoSuchFieldException {
        try {
            Field field = tClass.getDeclaredField(fieldName);
            return field;
        } catch (NoSuchFieldException e) {
            if (tClass.equals(Object.class)) {
                throw e;
            } else {
                return getDeclaredField(tClass.getSuperclass(), fieldName);
            }
        }
    }

    public static XBeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass) {
        XBeanInfo xBeanInfo = new XBeanInfo();
        xBeanInfo.setAClass(beanClass);
        boolean isSupperClass;
        // Check stopClass is a superClass of startClass.
        if (stopClass != null) {
            boolean isSuper = false;
            for (Class<?> c = beanClass.getSuperclass(); c != null; c = c.getSuperclass()) {
                if (c == stopClass) {
                    isSuper = true;
                }
            }
            if (!isSuper) {
                throw new BizException(stopClass.getName() + " not superclass of " +
                    beanClass.getName());
            }
        }
        beanClass.getDeclaredMethods();
        beanClass.getDeclaredFields();
        Field field = null;
        return xBeanInfo;
    }

    public static XBeanInfo getBeanInfo(Class<?> beanClass) {
        return getBeanInfo(beanClass, null);
    }

    public static XPropertyInfo findField(String fieldName, Class<?> beanClass) {
        return new XPropertyInfo();
    }

    public static boolean isNull(Object object) {
        return Objects.isNull(object);
    }

    public static boolean isNotNull(Object object) {
        return Objects.nonNull(object);
    }

    public static boolean isBlank(Object object) {
        if (object instanceof String) {
            return StringUtils.isBlank((String) object);
        } else {
            return isNull(object);
        }
    }

    public static boolean isNotBlank(Object object) {
        return !isBlank(object);
    }

    private static Map<String, BeanCopier> copierCache = new ConcurrentHashMap<>();

    /**
     * 如果在循环内拷贝推荐使用@Link##copy {@link BeanCopierWrap#copy(Object, Object)}
     *
     * @param src
     * @param tar
     */
    public static void copy(Object src, Object tar) {
        BeanCopier beanCopier = getCopier(src.getClass(), tar.getClass());
        beanCopier.copy(src, tar, null);
    }

    private static BeanCopier getCopier(Class<?> srcClass, Class<?> tarClass) {
        String key = srcClass.getName() + tarClass.getName();
        BeanCopier beanCopier = copierCache.get(key);
        if (beanCopier == null) {
            beanCopier = BeanCopier.create(srcClass, tarClass, false);
            copierCache.put(key, beanCopier);
        }
        return beanCopier;
    }

    //如果在循环中copy则通过BeanCopierWrap实例 copy调用
    public static class BeanCopierWrap {

        @Setter
        private BeanCopier beanCopier;

        public void copy(Object src, Object tar) {
//            if (beanCopier == null) {
//                beanCopier = getCopier(src.getClass(), tar.getClass());
//            }
            beanCopier.copy(src, tar, null);
        }
    }
}
